package com.lazyboyl.sharding.proxy.server;

import com.lazyboyl.sharding.proxy.backend.service.CurrencyService;
import com.lazyboyl.sharding.proxy.config.NettyConfigEnum;
import com.lazyboyl.sharding.proxy.net.entity.ShardingLoginInfo;
import com.lazyboyl.sharding.proxy.net.factory.FrontHandlerFactory;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.concurrent.*;

/**
 * @author linzef
 * @since 2021-06-28
 * 类描述：ShardingProxy服务器启动的主入口类
 */
@Component
public class ShardingProxyServer {

    /**
     * websocket的端口
     */
    @Value("${sharding.proxy.port}")
    private Integer port;

    /**
     * netty的boss线程数
     */
    @Value("${sharding.proxy.thread.boss}")
    private Integer bossThread;

    /**
     * netty的work线程数
     */
    @Value("${sharding.proxy.thread.work}")
    private Integer workThread;

    /**
     * 连接shardingProxy的账号
     */
    @Value("${sharding.proxy.user}")
    private String shardingProxyUser;

    /**
     * 连接shardingProxy的密码
     */
    @Value("${sharding.proxy.pass}")
    private String shardingProxyPass;

    /**
     * shardingProxy的库名
     */
    @Value("${sharding.proxy.database.name}")
    private String shardingProxyDatabaseName;

    @Autowired
    private CurrencyService currencyService;


    /**
     * 功能描述： 初始化配置，以及启动ShardingProxy
     */
    @PostConstruct
    public void init() {
        ExecutorService shardingProxySinglePool = new ThreadPoolExecutor(1, 1, 0, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<>(1024),
                Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
        shardingProxySinglePool.execute(() -> {
            try {
                start();
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
    }

    /**
     * 功能描述：启动netty
     *
     * @throws Exception 错误信息
     */
    protected void start() {
        try {
            ShardingLoginInfo shardingLoginInfo = new ShardingLoginInfo(port, bossThread, workThread, shardingProxyUser, shardingProxyPass, shardingProxyDatabaseName);
            ServerBootstrap bootstrap = new ServerBootstrap();
            EventLoopGroup boss = new NioEventLoopGroup(bossThread);
            EventLoopGroup work = new NioEventLoopGroup(workThread);
            bootstrap.group(boss, work).channel(NioServerSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG, 1024)
                    .childHandler(new FrontHandlerFactory(shardingLoginInfo, currencyService)).option(ChannelOption.ALLOCATOR,
                    PooledByteBufAllocator.DEFAULT)
                    .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, NettyConfigEnum.CONNECT_TIMEOUT_MILLIS.getIntegerValue())
                    .option(ChannelOption.SO_TIMEOUT, NettyConfigEnum.SO_TIMEOUT.getIntegerValue());
            ChannelFuture f = bootstrap.bind(port).sync();
            f.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

}
